/********************************************************************************
*
* File: ast.h
* The abstract syntax trees for the calculator
* Programmer: Leonidas Fegaras, UTA
* Date: 12/17/97
*
********************************************************************************/
//#include "gc.h"

#include <vector>
/* Put the names of all the different kinds of ASTs here */
/*
typedef enum { if_exp, eq_exp, lt_exp, gt_exp, le_exp, ne_exp, ge_exp, plus_exp, minus_exp,
               times_exp, div_exp, or_exp, and_exp, not_exp, call_exp, fnc_def,Sentence
} ast_kind;

static char* ast_names[] = {
   "if_exp", "eq_exp", "lt_exp", "gt_exp", "le_exp", "ne_exp", "ge_exp", "plus_exp", "minus_exp",
   "times_exp", "div_exp", "or_exp", "and_exp", "not_exp", "call_exp", "fnc_def","Sentence"
};
*/
typedef enum { program,Body,Declarations,VariableDeclaration,TypeDeclaration,ProcedureDeclaration,ArrayType,RecordType,Components,Component,FormalParameters,FunctionParameterSections,
               FunctionParameterSection,Statements,AssignmentStatement,ProcedureCallStatement,ReadStatement,WriteStatement,IfStatement,WhileStatement,LoopStatement,ForStatement,ExitStatement,
               ReturnStatement,ElsifStatements,ElsifStatement,WriteParameters,WriteExpressions,WriteExpression,WriteContents,Expressions,Expression,LeftValues,LeftValue,
               ActualParameters,CompleteValues,CompleteValue,Array,ArrayValues,ArrayValue,UnaryOperation,BinaryOperation,Identifiers,Identifier
} ast_kind;

static char* ast_names[] = {
   "program","Body","Declarations","VariableDeclaration","TypeDeclaration","ProcedureDeclaration","ArrayType","RecordType","Components","Component","FormalParameters","FunctionParameterSections",
   "FunctionParameterSection","Statements","AssignmentStatement","ProcedureCallStatement","ReadStatement","WriteStatement","IfStatement","WhileStatement","LoopStatement","ForStatement","ExitStatement",
   "ReturnStatement","ElsifStatements","ElsifStatement","WriteParameters","WriteExpressions","WriteExpression","WriteContents","Expressions","Expression","LeftValues","LeftValue",
   "ActualParameters","CompleteValues","CompleteValue","Array","ArrayValues","ArrayValue","UnaryOperation","BinaryOperation","Identifiers","Identifier"
};

/* This is a universal data structure that can capture any AST:
 * The node is an internal node and has a list of children (other ASTs),
 * while the other nodes are leaves       */

typedef struct ast {
  enum { int_ast, real_ast, var_ast, str_ast, node_ast } tag;
  union { long          integer;
          double        real;
          char*         variable;
          char*         string;
          struct
          {
            ast_kind          tag;
            struct ast_list*  arguments;
          } node;
      } info;
} ast;


typedef struct ast_list {
  ast*             elem;
  struct ast_list* next;
} ast_list;

typedef struct Exp
{
    enum {int_expression, real_expression, var_expression, string_expression} type;
    union
    {
        long integer;
        double real;
        char* variable;
        char* str;
    }value;
}Exp;

typedef struct identifier
{
    char* name;
    /*
    enum {int_identifier, real_identifier, var_identifier, string_identifier} type;
    union
    {
        long integer;
        double real;
        char* variable;
        char* str;
    }value;
    */
    Exp expression;
}identifier;

/* create an integer AST leaf */
ast* mk_int ( const long x );


/* create a floating point AST leaf */
ast* mk_real ( const double x );


/* create an AST leaf for a name */
ast* mk_var ( const char* x );


/* create a string AST leaf */
ast* mk_str ( const char* x );


/* create an internal AST node */
ast* mk_node ( const ast_kind tag, ast_list* args );


/* put an AST e in the beginning of the list of ASTs r */
ast_list* cons ( ast* e, ast_list* r );

/* put an AST E at the end of an existed list of ASTs r */
ast_list* PushBackAST(ast* e, ast_list* r);
/* the empty list of ASTs */
//#define null NULL
#define null 0


/* size of an AST list */
short length ( ast_list* );

/* reverse the order of ASTs in an AST list */
ast_list* reverse ( ast_list* );


/* printing functions for ASTs */
void print_ast_list ( ast_list* r,int layer );

void print_ast ( ast* x,int layer );

void RunProgram(ast* root,int layer);

void RunBody(ast* root,int layer);

void RunDeclarations(ast* root,int layer);

void RunVariableDeclaration(ast* root,int layer);

std::vector<char*> RunIdentifiers(ast* root,int layer);

char* RunIdentifier(ast* root,int layer);

Exp RunExpression(ast* root,int layer);

void RunNode(ast* root,int layer);

void Run(ast* root,int layer);
